/*
 * ConfigOperations.cpp
 *
 *  Created on: Apr 8, 2010
 *      Author: Lukasz Spintzyk
 */

#include "ConfigOperations.h"
#include "OtherFsOperations.h"
#include "Filesystem.h"
#include "InodeReader.h"
#include "DirectoryReader.h"
#include "FSException.h"
#include "ph.h"


namespace CudaCryptoFs
{

int getattr(const char *path, struct stat *stbuf) {
	try
	{
		memset(stbuf, 0, sizeof(struct stat));

		Filesystem* fs = getFS();
		DirectoryReader* dr = fs->getDirectoryReader();
		InodePtr inode = dr->path2Inode(path);



		stbuf->st_mode  = inode->d_mode ;
		stbuf->st_nlink = inode->d_linksCount;
		stbuf->st_ctim.tv_sec = inode->d_ctime;
		stbuf->st_atim.tv_sec = inode->d_atime;
		stbuf->st_mtim.tv_sec = inode->d_mtime;
		stbuf->st_size = inode->d_size;
		stbuf->st_blocks = inode->d_blocks;
		stbuf->st_gid = inode->d_gid;
		stbuf->st_uid = inode->d_uid;
		stbuf->st_ino = inode->d_num;
			//stbuf->st_blksize = fs->getSuperBlock().d_blockSize; //ignored
		return 0;

	}
	catch(FSException& e)
	{
		return -e.code;
	}
}

/*****************************************************************************/
/*****************************************************************************/

int chmod(const char *path, mode_t new_mode)
{
	// TODO write an plug
	Filesystem* fs = getFS();
	DirectoryReader* dr = fs->getDirectoryReader();
	InodeManager* iMgr = fs->getInodeReader();
	try
	{
		boost::shared_ptr<Inode> inode = dr->path2Inode(path);
		if (inode->d_uid == fuse_get_context()->uid)
		{
			inode->d_mode = new_mode;
			iMgr->setInode(inode->d_num, inode);
			return 0;
		}
	}
	catch(FSException& e)
	{
		return -ENOENT;
	}

	return -EPERM;
}

/*****************************************************************************/
/*****************************************************************************/

int chown(const char *path, uid_t uid, gid_t gid)
{
	// TODO write an plug
	Filesystem* fs = getFS();
	DirectoryReader* dr = fs->getDirectoryReader();
	InodeManager* iMgr = fs->getInodeReader();
	try
	{
		boost::shared_ptr<Inode> inode = dr->path2Inode(path);
		if (inode->d_uid == fuse_get_context()->uid)
		{
			inode->d_uid = uid;
			iMgr->setInode(inode->d_num, inode);
			return 0;
		}
	}
	catch(FSException& e)
	{
		return -ENOENT;
	}
	return -EPERM;
}

/*****************************************************************************/
/*****************************************************************************/

int utime(const char *path, struct utimbuf *)
{
	// TODO write an plug
	assert(!"DEPRECATED");
	return -ENOENT;
}

/*****************************************************************************/
/*****************************************************************************/

int utimens(const char * path, const struct timespec tv[2])
{
	// TODO write an plug
	Filesystem* fs = getFS();
	DirectoryReader* dr = fs->getDirectoryReader();
	InodeManager* iMgr = fs->getInodeReader();
	try
	{
		boost::shared_ptr<Inode> inode = dr->path2Inode(path);

		if (inode->d_uid == fuse_get_context()->uid)
		{
			inode->d_atime = tv[0].tv_sec;
			inode->d_mtime = tv[1].tv_sec;
			iMgr->setInode(inode->d_num, inode);
			return 0;
		}

	}
	catch(FSException& e)
	{
		return -ENOENT;
	}
	return -EPERM;
}

/*****************************************************************************/
/*****************************************************************************/

int setxattr(const char *, const char *, const char *, size_t, int)
{
	// TODO write an plug
		return -ENOENT;
}

/*****************************************************************************/
/*****************************************************************************/

int getxattr(const char *, const char *, char *, size_t)
{
	// TODO write an plug
		return -ENOENT;
}

/*****************************************************************************/
/*****************************************************************************/

int listxattr(const char *, char *, size_t)
{
	// TODO write an plug
		return -ENOENT;
}

/*****************************************************************************/
/*****************************************************************************/

int removexattr(const char *, const char *)
{
	// TODO write an plug
		return -ENOENT;
}

} //end namespace CudaCryptoFs
